package com.axonactive.yolo.service.interfaces;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import com.axonactive.yolo.domain.SubscribedFlight;
import com.axonactive.yolo.dto.Email;
import com.axonactive.yolo.dto.Flight;
import com.axonactive.yolo.dto.TaskAlert;
import com.axonactive.yolo.util.Utils;
@PropertySource("classpath:application.properties")
@Service
public class EmailService {
	
	private static Logger LOGGER = Logger.getLogger(EmailService.class);

	@Autowired
	private JavaMailSender mailSender;

	@Autowired
	private TemplateEngine templateEngine;

	@Autowired
	private ExchangeRateService exchangeRateService;

	@Resource
	public Environment env;

	private static String LOGIN_LINK = "http://dev.yolo.axonactive.vn.local/yoloflight/subscribe/list.html";
	
	private static String LOGIN_LINK_TASK = "http://dev.yolo.axonactive.vn.local/yoloflight/task/list.html";

	public void sendEmail_(Email email) throws MessagingException {
		// Prepare message using a Spring helper
		final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
		final MimeMessageHelper message = new MimeMessageHelper(mimeMessage,
				"UTF-8");
		message.setFrom(env.getRequiredProperty("email.from"));
		message.setSubject(email.getSubject());
		message.setTo(email.getTo());

		// Create the HTML body using Thymeleaf
		final String htmlContent = this.templateEngine.process(
				email.getTemplate(), email.getBody());
		message.setText(htmlContent, true /* isHtml */);

		// Send email
		this.mailSender.send(mimeMessage);
	}

	/**
	 * set email template for canceled oneway flight
	 *
	 * @return email template for canceled oneway flight
	 */
	public Email setOneWayEmailCancelTemplate(String emailStr, SubscribedFlight subcribedFlight, String subject, String template, String userCurrencyCode) {
		Email email = new Email();
		email.setSubject(subject);
		email.setTo(emailStr);
		email.setTemplate(template);

		Context ctx = new Context();
		ctx = setContextNewOutboundForEmail(ctx, subcribedFlight, userCurrencyCode);
		ctx.setVariable("email", emailStr);
		ctx.setVariable("subscriptionDate", new Date());
		ctx.setVariable("login_link", LOGIN_LINK);
		email.setBody(ctx);

		return email;
	};

	/**
	 * set email template for canceled roundtrip flight
	 *
	 * @return email template for canceled roundtrip flight
	 */
	public Email setRoundTripEmailCancelTemplate(String emailStr, SubscribedFlight subcribedFlight, String subject, String template, String userCurrencyCode) {
		Email email = new Email();
		email.setSubject(subject);
		email.setTo(emailStr);
		email.setTemplate(template);

		Context ctx = new Context();
		ctx = setContextNewOutboundForEmail(ctx, subcribedFlight, userCurrencyCode);
		ctx = setContextNewInboundForEmail(ctx, subcribedFlight);
		ctx.setVariable("email", emailStr);
		ctx.setVariable("subscriptionDate", new Date());
		ctx.setVariable("login_link", LOGIN_LINK);
		email.setBody(ctx);

		return email;
	};

	/**
	 * set email template for oneWay
	 *
	 * @return email template
	 */
	public Email setOneWayEmailTemplate(String emailStr, SubscribedFlight subcribedFlight, String subject, String template, String userCurrencyCode) {
		Email email = new Email();
		email.setSubject(subject);
		email.setTo(emailStr);
		email.setTemplate(template);

		Context ctx = new Context();
		ctx = setContextNewOutboundForEmail(ctx, subcribedFlight, userCurrencyCode);
		ctx = setContextOutboundBeforeForEmail(ctx, subcribedFlight, userCurrencyCode);
		ctx.setVariable("email", emailStr);
		ctx.setVariable("subscriptionDate", new Date());
		ctx.setVariable("login_link", LOGIN_LINK);
		email.setBody(ctx);

		return email;
	};
	
	/**
	 * set email template for oneWay flight task
	 *
	 * @return email template
	 */
	public Email setOneWayTaskEmailTemplate(String emailStr, List<TaskAlert> taskAlerts, String subject, String template) {
		Email email = new Email();
		email.setSubject(subject);
		email.setTo(emailStr);
		email.setTemplate(template);

		Context ctx = new Context();
		ctx.setVariable("email", emailStr);
		ctx.setVariable("login_link", LOGIN_LINK_TASK);
		ctx.setVariable("taskAlerts", taskAlerts);
		email.setBody(ctx);

		return email;
	};
	
	/**
	 * set email template for roundTrip flight task
	 *
	 * @return email template
	 */
	public Email setRoundTripTaskEmailTemplate(String emailStr, List<TaskAlert> taskAlerts, String subject, String template) {
		Email email = new Email();
		email.setSubject(subject);
		email.setTo(emailStr);
		email.setTemplate(template);

		Context ctx = new Context();
		ctx.setVariable("email", emailStr);
		ctx.setVariable("login_link", LOGIN_LINK_TASK);
		ctx.setVariable("taskAlerts", taskAlerts);
		email.setBody(ctx);

		return email;
	};

	/**
	 * set email template for roundTrip
	 *
	 * @return email template
	 */
	public Email setRoundTripEmailTemplate(String emailStr, SubscribedFlight subcribedFlight, String subject, String template, String userCurrencyCode) {
		Email email = new Email();
		email = setOneWayEmailTemplate(emailStr, subcribedFlight, subject, template, userCurrencyCode);

		Context ctx = new Context();
		ctx = setContextNewOutboundForEmail(ctx, subcribedFlight, userCurrencyCode);
		ctx = setContextOutboundBeforeForEmail(ctx, subcribedFlight, userCurrencyCode);
		ctx = setContextNewInboundForEmail(ctx, subcribedFlight);
		ctx = setContextInboundBeforeForEmail(ctx, subcribedFlight);
		ctx.setVariable("email", emailStr);
		ctx.setVariable("subscriptionDate", new Date());
		ctx.setVariable("login_link", LOGIN_LINK);
		email.setBody(ctx);

		return email;
	};

	/**
	 * set email context for new Outbound
	 *
	 * @return New Outbound context
	 */
	public Context setContextNewOutboundForEmail(Context ctx, SubscribedFlight subcribedFlight, String userCurrencyCode) {

		// new outbound information
		ctx.setVariable("outbound_flight_carrier_new",
				subcribedFlight.getOutBoundCarriers());
		ctx.setVariable("outbound_from_new", subcribedFlight.getOutboundCode());
		ctx.setVariable("outbound_date_new", subcribedFlight.getOutBoundDate());
		ctx.setVariable("outbound_departure_time_new",
				subcribedFlight.getOutBoundDepartureTime());
		ctx.setVariable("outbound_to_new", subcribedFlight.getInboundCode());
		ctx.setVariable("outbound_arrival_time_new",
				subcribedFlight.getOutBoundArrivalTime());
		ctx.setVariable("outbound_stops_new", subcribedFlight.getOutBoundNumStops());
		ctx.setVariable("outbound_airport_new", subcribedFlight.getOutBoundAirportsExpanded());
		ctx.setVariable("price_new", Utils.roundNDigit(exchangeRateService.convert(subcribedFlight.getPrice(), subcribedFlight.getCurrencyCode(), userCurrencyCode), 2));
		ctx.setVariable("currency_code_new", userCurrencyCode);
		return ctx;
	}

	/**
	 * set email context for Outbound before
	 *
	 * @return Outbound before context
	 */
	public Context setContextOutboundBeforeForEmail(Context ctx, SubscribedFlight subcribedFlight, String userCurrencyCode) {

		// outbound information before
		ctx.setVariable("outbound_flight_carrier_old",
				subcribedFlight.getOutBoundCarriers());
		ctx.setVariable("outbound_from_old", subcribedFlight.getOutboundCode());
		ctx.setVariable("outbound_date_old", subcribedFlight.getOutBoundDate());
		ctx.setVariable("outbound_departure_time_old",
				subcribedFlight.getOutBoundDepartureTimeBefore());
		ctx.setVariable("outbound_to_old", subcribedFlight.getInboundCode());
		ctx.setVariable("outbound_arrival_time_old",
				subcribedFlight.getOutBoundArrivalTimeBefore());
		ctx.setVariable("outbound_stops_new", subcribedFlight.getOutBoundNumStops());
		ctx.setVariable("outbound_airport_new", subcribedFlight.getOutBoundAirportsExpanded());
		ctx.setVariable("price_old", Utils.roundNDigit(exchangeRateService.convert(subcribedFlight.getPriceBefore(), subcribedFlight.getCurrencyCode(), userCurrencyCode), 2));
		ctx.setVariable("currency_code_old", userCurrencyCode);
		return ctx;
	}

	/**
	 * set email context for new Inbound
	 *
	 * @return new Inbound context
	 */
	public Context setContextNewInboundForEmail(Context ctx,
			SubscribedFlight subcribedFlight) {

		// new inbound information
		ctx.setVariable("typeoftrip", "none");
		ctx.setVariable("inbound_flight_carrier_new",
				subcribedFlight.getInBoundCarriers());
		ctx.setVariable("inbound_date_new", subcribedFlight.getInBoundDate());
		ctx.setVariable("inbound_from_new", subcribedFlight.getInboundCode());
		ctx.setVariable("inbound_departure_time_new",
				subcribedFlight.getInBoundDepartureTime());
		ctx.setVariable("inbound_to_new", subcribedFlight.getOutboundCode());
		ctx.setVariable("inbound_arrival_time_new",
				subcribedFlight.getInBoundArrivalTime());
		ctx.setVariable("inbound_stops_new", subcribedFlight.getInBoundNumStops());
		ctx.setVariable("inbound_airport_new", subcribedFlight.getInBoundAirportsExpanded());
		return ctx;
	}

	/**
	 * set email context for Inbound before
	 *
	 * @return Inbound before context
	 */
	public Context setContextInboundBeforeForEmail(Context ctx,
			SubscribedFlight subcribedFlight) {

		// inbound information before
		ctx.setVariable("inbound_flight_carrier_old",
				subcribedFlight.getInBoundCarriers());
		ctx.setVariable("inbound_date_old", subcribedFlight.getInBoundDate());
		ctx.setVariable("inbound_from_old", subcribedFlight.getInboundCode());
		ctx.setVariable("inbound_departure_time_old",
				subcribedFlight.getOutBoundDepartureTimeBefore());
		ctx.setVariable("inbound_to_old", subcribedFlight.getOutboundCode());
		ctx.setVariable("inbound_arrival_time_old",
				subcribedFlight.getInBoundArrivalTimeBefore());
		ctx.setVariable("inbound_stops_new", subcribedFlight.getInBoundNumStops());
		ctx.setVariable("inbound_airport_new", subcribedFlight.getInBoundAirportsExpanded());
		return ctx;
	}
	
	/**
	 * @param emailstr
	 * @param reset_link
	 * @return
	 */
	public boolean sendResetLink(String emailstr, String reset_link) {
		try {
			Email email = new Email();
			email.setSubject(env
					.getRequiredProperty("email.reset.password.subject"));
			email.setTo(emailstr);
			email.setTemplate("reset-password-email-template");

			Context ctx = new Context();
			ctx.setVariable("email", emailstr);
			ctx.setVariable("subscriptionDate", new Date());
			ctx.setVariable("reset_link", reset_link);

			email.setBody(ctx);
			sendEmail_(email);
			return true;
		} catch (MessagingException e) {
			LOGGER.info("Cant send Reset Link", e);
		} catch (Exception e) {
			LOGGER.info("Error", e);
		}
		return false;
	}
	/**
	 * @param emailstr
	 * @param login_link
	 * @return
	 */
	public boolean sendResetSuccess(String emailstr, String login_link) {
		try {
			Email email = new Email();
			email.setSubject(env
					.getRequiredProperty("email.reset.password.subject.success"));
			email.setTo(emailstr);
			email.setTemplate("reset-password-success-email-template");

			Context ctx = new Context();
			ctx.setVariable("email", emailstr);
			ctx.setVariable("subscriptionDate", new Date());
			ctx.setVariable("login_link", login_link);

			email.setBody(ctx);
			sendEmail_(email);
			return true;
		} catch (MessagingException e) {
			LOGGER.error("Cant send message", e);
		} catch (Exception e) {
			LOGGER.error("Cant send email ", e);
		}
		return false;
	}
	
	/**
	 * @param emailStr
	 * @param productName
	 * @param activateLink
	 * @return
	 */
	public boolean sendActivateEmail(String emailStr, String productName,
			String activateLink) {
		try {
			Email email = new Email();
			email.setSubject(env.getRequiredProperty("email.activation"));
			email.setTo(emailStr);
			email.setTemplate("activate-account-email-template");

			Context ctx = new Context();
			ctx.setVariable("email", emailStr);
			ctx.setVariable("product_name", productName);
			ctx.setVariable("activate_link", activateLink);

			email.setBody(ctx);
			sendEmail_(email);
			return true;
		} catch (MessagingException e) {
			LOGGER.info("Cant send Activation Email ", e);
		} catch (Exception e) {
			LOGGER.info("Error", e);
		}
		return false;
	}

	
}